Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit correct alignment information for loads/store of small aggregates #24472

Merged
merged 1 commit into from
Apr 18, 2015

Conversation

dotdash
Copy link
Contributor

@dotdash dotdash commented Apr 15, 2015

Loading from and storing to small aggregates happens by casting the
aggregate pointer to an appropriately sized integer pointer to avoid
the usage of first class aggregates which would lead to less optimized
code.

But this means that, for example, a tuple of type (i16, i16) will be
loading through an i32 pointer and because we currently don't provide
alignment information LLVM assumes that the load should use the ABI
alignment for i32 which would usually be 4 byte alignment. But the
alignment requirement for the (i16, i16) tuple will usually be just 2
bytes, so we're overestimating alignment, which invokes undefined
behaviour.

Therefore we must emit appropriate alignment information for
stores/loads through such casted pointers.

Fixes #23431

@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

@alexcrichton
Copy link
Member

Nice find! Could a test case be added as well for this? (perhaps a run-make test?)

@alexcrichton
Copy link
Member

Er looks like I mistook this issue for another, never mind!

@nikomatsakis
Copy link
Contributor

This does indeed look great, but I would very much like to see some tests. It'd probably be good to setup some kind of infrastructure that can verify properties of generated LLVM IR (perhaps this is what @alexcrichton was suggesting?). (But I'm not quite sure how that ought to look -- it'd obviously be hard to isolate the relevant load.)

Anyway, r+ from me, but I'd like to know whether @dotdash has any thoughts on a way to write some sort of easily reproducible test -- one though I have is to create a big byte buffer and load an aggregate from there, which would allow us to observe if the alignment is wrong.

@dotdash
Copy link
Contributor Author

dotdash commented Apr 16, 2015

I can't think of anything that would trigger on x86 hardware, because AFAIK the relevant instructions don't care about alignment. The problem was discovered on an ARMv5 that has rather "interesting" behaviour on unaligned loads.

The only thing I can think of would indeed be to verify the LLVM IR, but we have no infrastructure for that yet. What do you think of repurposing the codegen test directory to perform checks on the LLVM IR using LLVM's FileCheck? While the intention behind the code size ratio tests that currently live there was good, we never really got a meaningful number of tests there, and the idea behind them is somewhat flawed, because things like the lifetime or assume intrinsics can inflate the code size, yet lead to better results.

@dotdash
Copy link
Contributor Author

dotdash commented Apr 16, 2015

one though I have is to create a big byte buffer and load an aggregate from there, which would allow us to observe if the alignment is wrong.

To clarify, the alignment of the data is correct, but the alignment communicated to LLVM is wrong, so on some architectures, it lowers it to machine instructions that only work with the alignment that was communicated to LLVM, not the actual alignment of the data. So I can't think of a way to observe the problem easily from rust code in a portable way.

@alexcrichton
Copy link
Member

@bors: r=nikomatsakis e153dea

Ah well, maybe we'll have our own testing infrastructure for this one day!

Manishearth added a commit to Manishearth/rust that referenced this pull request Apr 17, 2015
 Loading from and storing to small aggregates happens by casting the
aggregate pointer to an appropriately sized integer pointer to avoid
the usage of first class aggregates which would lead to less optimized
code.

But this means that, for example, a tuple of type (i16, i16) will be
loading through an i32 pointer and because we currently don't provide
alignment information LLVM assumes that the load should use the ABI
alignment for i32 which would usually be 4 byte alignment. But the
alignment requirement for the (i16, i16) tuple will usually be just 2
bytes, so we're overestimating alignment, which invokes undefined
behaviour.

Therefore we must emit appropriate alignment information for
stores/loads through such casted pointers.

Fixes rust-lang#23431
Manishearth added a commit to Manishearth/rust that referenced this pull request Apr 17, 2015
 Loading from and storing to small aggregates happens by casting the
aggregate pointer to an appropriately sized integer pointer to avoid
the usage of first class aggregates which would lead to less optimized
code.

But this means that, for example, a tuple of type (i16, i16) will be
loading through an i32 pointer and because we currently don't provide
alignment information LLVM assumes that the load should use the ABI
alignment for i32 which would usually be 4 byte alignment. But the
alignment requirement for the (i16, i16) tuple will usually be just 2
bytes, so we're overestimating alignment, which invokes undefined
behaviour.

Therefore we must emit appropriate alignment information for
stores/loads through such casted pointers.

Fixes rust-lang#23431
@bors
Copy link
Contributor

bors commented Apr 17, 2015

⌛ Testing commit e153dea with merge 1963a3d...

@bors
Copy link
Contributor

bors commented Apr 17, 2015

💔 Test failed - auto-linux-64-nopt-t

@alexcrichton
Copy link
Member

@bors: retry

On Fri, Apr 17, 2015 at 9:26 AM, bors notifications@github.com wrote:

[image: 💔] Test failed - auto-linux-64-nopt-t
http://buildbot.rust-lang.org/builders/auto-linux-64-nopt-t/builds/4522


Reply to this email directly or view it on GitHub
#24472 (comment).

@bors
Copy link
Contributor

bors commented Apr 18, 2015

⌛ Testing commit e153dea with merge 0773d10...

@bors
Copy link
Contributor

bors commented Apr 18, 2015

💔 Test failed - auto-mac-64-opt

Loading from and storing to small aggregates happens by casting the
aggregate pointer to an appropriately sized integer pointer to avoid
the usage of first class aggregates which would lead to less optimized
code.

But this means that, for example, a tuple of type (i16, i16) will be
loading through an i32 pointer and because we currently don't provide
alignment information LLVM assumes that the load should use the ABI
alignment for i32 which would usually be 4 byte alignment. But the
alignment requirement for the (i16, i16) tuple will usually be just 2
bytes, so we're overestimating alignment, which invokes undefined
behaviour.

Therefore we must emit appropriate alignment information for
stores/loads through such casted pointers.

Fixes rust-lang#23431
@dotdash
Copy link
Contributor Author

dotdash commented Apr 18, 2015

@bors r=nikomatsakis 78745a4

@bors
Copy link
Contributor

bors commented Apr 18, 2015

⌛ Testing commit 78745a4 with merge 1b2251b...

Manishearth added a commit to Manishearth/rust that referenced this pull request Apr 18, 2015
Loading from and storing to small aggregates happens by casting the
aggregate pointer to an appropriately sized integer pointer to avoid
the usage of first class aggregates which would lead to less optimized
code.

But this means that, for example, a tuple of type (i16, i16) will be
loading through an i32 pointer and because we currently don't provide
alignment information LLVM assumes that the load should use the ABI
alignment for i32 which would usually be 4 byte alignment. But the
alignment requirement for the (i16, i16) tuple will usually be just 2
bytes, so we're overestimating alignment, which invokes undefined
behaviour.

Therefore we must emit appropriate alignment information for
stores/loads through such casted pointers.

Fixes rust-lang#23431
@bors
Copy link
Contributor

bors commented Apr 18, 2015

⛄ The build was interrupted to prioritize another pull request.

@bors
Copy link
Contributor

bors commented Apr 18, 2015

⌛ Testing commit 78745a4 with merge 3e08c96...

@bors
Copy link
Contributor

bors commented Apr 18, 2015

⛄ The build was interrupted to prioritize another pull request.

bors added a commit that referenced this pull request Apr 18, 2015
@bors bors merged commit 78745a4 into rust-lang:master Apr 18, 2015
@dotdash dotdash deleted the 23431 branch May 8, 2015 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorrectly generated code for struct alignments
5 participants